package l2ft.gameserver.model.entity.events.fightclubmanager;

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;

import l2ft.gameserver.data.xml.holder.EventHolder;
import l2ft.gameserver.data.xml.holder.FightClubMapHolder;
import l2ft.gameserver.handler.bbs.CommunityBoardManager;
import l2ft.gameserver.handler.bbs.ICommunityBoardHandler;
import l2ft.gameserver.listener.actor.player.OnPlayerExitListener;
import l2ft.gameserver.model.Party;
import l2ft.gameserver.model.Player;
import l2ft.gameserver.model.base.ClassId;
import l2ft.gameserver.model.entity.events.EventType;
import l2ft.gameserver.model.entity.events.fightclubmanager.FightClubEventManager.CLASSES;
import l2ft.gameserver.model.entity.events.impl.AbstractFightClub;
import l2ft.gameserver.model.entity.events.impl.AbstractFightClub.EVENT_STATE;
import l2ft.gameserver.model.entity.league.League;
import l2ft.gameserver.network.l2.components.ChatType;
import l2ft.gameserver.network.l2.s2c.Say2;
import l2ft.gameserver.utils.Util;

public class FightClubGameRoom
{
	private class LeaveListener implements OnPlayerExitListener
	{
		@Override
		public void onPlayerExit(Player player)
		{
			if(_creator.equals(player))
				changeCreator();
			leaveRoom(player);
		}
	}
	
	private static int LAST_INDEX = 0;
	
	private int _index;
	private Player _creator;
	private String _name;
	private League _minLeague;
	private League _maxLeague;
	private int _gameType;
	private AbstractFightClub _existingGame;
	private boolean _blockJoining;//Invoked by admin
	private boolean _blockStartingEvent;//Invoked by admin
	
	//Kick
	private List<Player> _playersClickedChangeCreator = new ArrayList<>();
	
	//Players in Teamed game:
	private List<FightClubRoomTeam> _teams;
	//Players in FFA:
	private List<FightClubRoomConnection> _ffaConnections;
	private List<Player> _ffaPlayers;
	
	//Leave listener
	private LeaveListener _leaveListener = new LeaveListener();
	
	//Game Type vars
	private boolean _teamed;
	private int _roomMaxPlayers;
	private int _teamsCount;
	
	public FightClubGameRoom(Player creator, String name, League minLeague, League maxLeague, int gameType, int teams)
	{
		_index = ++LAST_INDEX;
		_creator = creator;
		_name = name;
		_minLeague = minLeague;
		_maxLeague = maxLeague;
		_gameType = gameType;
		_teamsCount = teams;
		
		_teams = new CopyOnWriteArrayList<>();
		for(int i = 0;i<_teamsCount;i++)
			_teams.add(new FightClubRoomTeam());
		_ffaPlayers = new CopyOnWriteArrayList<>();
		_ffaConnections = new CopyOnWriteArrayList<>();
		
		setupGameType();
		
		addAlonePlayer(creator);
	}
	
	private void setupGameType()
	{
		AbstractFightClub event = EventHolder.getInstance().getEvent(EventType.FIGHT_CLUB_EVENT, _gameType);
		_teamed = event.isTeamed();

		String changedEventName = Util.getChangedEventName(event);
		System.out.println("changed event name:"+changedEventName);
		_roomMaxPlayers = FightClubMapHolder.getInstance().getMaxPlayersForEvent(changedEventName);
	}
	
	public void changeTeamCount(int newCount)
	{
		if(!isTeamed())
			return;
		
		List<FightClubRoomConnection> allConnections = new ArrayList<>();
		for(FightClubRoomTeam team : _teams)
			for(FightClubRoomParty party : team.getPartys())
				for(FightClubRoomConnection conn : party.getConnections())
					allConnections.add(conn);
		
		_teamsCount = newCount;
		
		_teams = new CopyOnWriteArrayList<>();
		for(int i = 0;i<_teamsCount;i++)
			_teams.add(new FightClubRoomTeam());
		
		for(FightClubRoomConnection conn : allConnections)
			chooseTeamAndParty(conn);
		
		updateCommunity();
	}
	
	public void changeSettings(String newName, League newMinLeague, League newMaxLeague, int newGameType, int newTeamCount)
	{
		_name = newName;
		_minLeague = newMinLeague;
		_maxLeague = newMaxLeague;

		if(_gameType != newGameType)//GameType changed
		{
			_gameType = newGameType;
			boolean wasTeamed = _teamed;
			setupGameType();
			if(wasTeamed && !_teamed)//If game changed to FFA
			{
				for(FightClubRoomTeam team : _teams)
					for(FightClubRoomParty party : team.getPartys())
						for(FightClubRoomConnection conn : party.getConnections())
						{
							if(conn.getMembersCount() > 1)
								_ffaConnections.add(conn);
							for(Player player : conn.getMembers())
								_ffaPlayers.add(player);
						}
				_teams.clear();
			}
			else if(!wasTeamed && _teamed)//If game changed to teamed
			{
				for(Player player : _ffaPlayers)
					addAlonePlayer(player);
				
				_ffaConnections.clear();
				_ffaPlayers.clear();
			}
		}
		
		updateCommunity();
	}

	public void destroyMe()
	{
		ICommunityBoardHandler handler = CommunityBoardManager.getInstance().getCommunityHandler("_fightClubChooseGame_");
		Say2 packet = new Say2(0, ChatType.COMMANDCHANNEL_ALL, getName(), "Room has been destroyed by Creator!");
		System.out.println("all members count:"+getAllPlayers());
		for(Player member : getAllPlayers())
		{
			member.setFightClubGameRoom(null);
			handler.onBypassCommand(member, "_fightClubChooseGame_");
			member.sendPacket(packet);
		}
		quietlyDestroy();
	}

	public void quietlyDestroy()
	{
		_ffaConnections.clear();
		_ffaPlayers.clear();
		_teams.clear();
		_existingGame = null;
		for(Player player : getAllPlayers())
			player.removeListener(_leaveListener);
	}
	
	public void clickChangeCreator(Player player)
	{
		_playersClickedChangeCreator.add(player);
		
		if(player.equals(getCreator()))
			changeCreator();
		else
			checkChangeCreator();
	}
	
	public boolean alreadyClickedChangeCretor(Player player)
	{
		return _playersClickedChangeCreator.contains(player);
	}
	
	private void checkChangeCreator()
	{
		int realClicks = 0;
		for(Player player : _playersClickedChangeCreator)
			if(player != null && player.isOnline() && player.getFightClubGameRoom() != null && this.equals(player.getFightClubGameRoom()))
				realClicks ++;
		
		if(realClicks >= (double)getPlayersInside()/3.);
		{
			changeCreator();
		}
	}
	
	private void changeCreator()
	{
		Player newLeader = null;
		int winningPower = -1;
		
		for(Player player : getAllPlayers())
		{
			if(player.equals(_creator))
				continue;
			int power = 0;
			if(player.isClanLeader())
				power = 3;
			else if(player.getParty() != null && player.getParty().getPartyLeader().equals(player))
				power = 2;
			else if(player.getClan() != null)
				power = 1;
			
			if(power > winningPower)
				newLeader = player;
		}
		
		if(newLeader == null)
		{
			destroyMe();
		}
		else
		{
			_creator = newLeader;
			_creator.sendMessage("You are now room Creator!");
			Say2 packet = new Say2(_creator.getObjectId(), ChatType.COMMANDCHANNEL_ALL, _creator.getName(), "I am new Room Creator!");
			for(Player player : getAllPlayers())
				player.sendPacket(packet);
		}
	}
	
	public void leaveRoom(Player player)
	{
		if(isTeamed())
		{
			for(FightClubRoomTeam team : getTeams())
				for(FightClubRoomParty party : team.getPartys())
				{
					party.removeMember(player);
					player.setFightClubGameRoom(null);
				}	
		}
		else
		{
			for(FightClubRoomConnection conn : _ffaConnections)
				if(conn.getMembers().contains(player))
				{
					if(conn.getMembersCount() == 1)
						_ffaConnections.remove(conn);
					else
						conn.getMembers().remove(player);
					break;
				}
			
			_ffaPlayers.remove(player);
			player.setFightClubGameRoom(null);
		}
		
		player.removeListener(_leaveListener);
		
		updateCommunity();
	}

	public void stopCountDown()
	{
		if(getGame() != null)
		{
			getGame().stopFirstCountDown();
			getGame().destroyMe();
			_existingGame = null;
		}
	}
	
	public void blockJoiningRoom(boolean b)
	{
		_blockJoining = b;
	}
	
	public void blockJoiningRoom()
	{
		_blockJoining = !_blockJoining;
	}
	
	public boolean isJoiningBlocked()
	{
		return _blockJoining;
	}
	
	public void blockStartingEvent()
	{
		_blockStartingEvent = !_blockStartingEvent;
	}
	
	public boolean isStartingEventBlocked()
	{
		return _blockStartingEvent;
	}
	
	public int getGameType()
	{
		return _gameType;
	}
	
	public int getIndex()
	{
		return _index;
	}
	
	public Player getCreator()
	{
		return _creator;
	}
	
	public String getName()
	{
		return _name;
	}
	
	public League getMinLeague()
	{
		return _minLeague;
	}
	
	public League getMaxLeague()
	{
		return _maxLeague;
	}
	
	public int getMaxPlayers()
	{
		return _roomMaxPlayers;
	}
	
	public int getTeamsCount()
	{
		return _teamsCount;
	}
	
	public boolean isTeamed()
	{
		return _teamed;
	}
	
	public int getSlotsLeft()
	{
		System.out.println("max players:"+getMaxPlayers()+" players inside:"+getPlayersInside());
		return getMaxPlayers() - getPlayersInside();
	}
	
	public AbstractFightClub getGame()
	{
		return _existingGame;
	}
	
	public void setGame(AbstractFightClub game)
	{
		_existingGame = game;
	}
	
	public AbstractFightClub getGameForType()
	{
		return EventHolder.getInstance().getEvent(EventType.FIGHT_CLUB_EVENT, _gameType);
	}
	
	public int getPlayersInside()
	{
		if(getGame() == null)
		{
			int playersInside = 0;
			if(isTeamed())
			{
				for(FightClubRoomTeam team : _teams)
					playersInside += team.getMembersCount();
			}
			else
			{
				playersInside = _ffaPlayers.size();
			}
			return playersInside;
		}
		else
		{
			return getGame().getPlayers(AbstractFightClub.FIGHTING_PLAYERS, AbstractFightClub.LOGGED_OFF_PLAYERS, AbstractFightClub.REGISTERED_PLAYERS).size();
		}
	}
	
	/**
	 * !!! @Don't @change @that @list!!!
	 */
	public List<Player> getAllPlayers()
	{
		if(isTeamed())
		{
			List<Player> players = new ArrayList<>();
			for(FightClubRoomTeam team : _teams)
				for(FightClubRoomParty party : team.getPartys())
					players.addAll(party.getMembers());
			return players;
		}
		else
		{
			return _ffaPlayers;
		}
	}
	
	/**
	 * If event is FFA, returns empty list
	 */
	public List<FightClubRoomTeam> getTeams()
	{
		return _teams;
	}

	synchronized void addAlonePlayer(Player player)
	{
		player.setFightClubGameRoom(this);
		List<FightClubRoomConnection> connections = getConnectionsToJoin(player);
		removeConnections(connections);
		
		List<Player> allPlayersInConnections = new ArrayList<>();
		allPlayersInConnections.add(player);
		for(FightClubRoomConnection conn : connections)
			allPlayersInConnections.addAll(conn.getMembers());
		
		FightClubRoomConnection conn = createNewConnection(allPlayersInConnections);
		if(isTeamed())
		{
			addPlayers(conn);
		}
		else
		{
			_ffaPlayers.add(player);
			_ffaConnections.add(conn);
		}
		
		player.addListener(_leaveListener);
		
		updateCommunity();
	}
	
	private void removeConnections(List<FightClubRoomConnection> connections)
	{
		if(isTeamed())
		{
			for(FightClubRoomConnection conn : connections)
			{
				loop:for(FightClubRoomTeam team : getTeams())
					for(FightClubRoomParty party : team.getPartys())
						for(FightClubRoomConnection existingConnection : party.getConnections())
							if(existingConnection.equals(conn))
							{
								party.removeConnection(existingConnection);
								break loop;
							}
			}
		}
		else
		{
			for(FightClubRoomConnection conn : connections)
			{
				for(FightClubRoomConnection existingConnection : _ffaConnections)
					if(existingConnection.equals(conn))
					{
						_ffaConnections.remove(existingConnection);
						break;
					}
			}
		}
		
	}

	private List<FightClubRoomConnection> getConnectionsToJoin(Player player)
	{
		List<FightClubRoomConnection> connections = new ArrayList<>();
		if(isTeamed())
		{
			for(FightClubRoomTeam team : getTeams())
				for(FightClubRoomParty party : team.getPartys())
					loop:for(FightClubRoomConnection existingConnection : party.getConnections())
						for(Player existingPlayer : existingConnection.getMembers())
						{
							if(checkIfShouldBeConnected(player, existingPlayer))
							{
								connections.add(existingConnection);
								break loop;
							}
						}
		}
		else
		{
			for(FightClubRoomConnection existingConnection : _ffaConnections)
				loop:for(Player existingPlayer : existingConnection.getMembers())
				{
					if(checkIfShouldBeConnected(player, existingPlayer))
					{
						connections.add(existingConnection);
						break loop;
					}
				}
		}
		
		return connections;
	}
	
	private boolean checkIfShouldBeConnected(Player player1, Player player2)
	{
		//Party
		if(player1.getParty() != null && player2.getParty() != null && player1.getParty().equals(player2.getParty()))
			return true;
		
		//Clan
		if(player1.getClan() != null && player1.getClanId() == player2.getClanId())
			return true;
		
		//Ally
		if(player1.getAlliance() != null && player1.getAllyId() == player2.getAllyId())
			return true;
		
		//If they are friends, but one of them doesn't have any clan
		if((player1.getClan() == null || player2.getClan() == null) && player1.getFriendList().getOnlineFriends().contains(player2))
			return true;
		
		return false;
	}
	
	private void updateCommunity()
	{
		if(getGame() == null || getGame().getState() == EVENT_STATE.COUNT_DOWN)
		{
			ICommunityBoardHandler handler = CommunityBoardManager.getInstance().getCommunityHandler("_fightClubGameRoom_");
			
			for(Player member : getAllPlayers())
				handler.onBypassCommand(member, "_fightClubGameRoom_"+getIndex());
		}
	}
	
	private int TEAM_INDEX = 0;
	public class FightClubRoomTeam
	{
		private int _index;
		private List<FightClubRoomParty> _partys;
		
		private int PARTY_INDEX = 0;
		
		private FightClubRoomTeam()
		{
			_index = TEAM_INDEX++;
			_partys = new ArrayList<>();
		}
		
		public int getIndex()
		{
			return _index;
		}
		
		public List<FightClubRoomParty> getPartys()
		{
			return _partys;
		}
		
		public int getMembersCount()
		{
			int count = 0;
			for(FightClubRoomParty party : _partys)
				count += party.getMembersCount();
			return count;
		}
	}
	
	public class FightClubRoomParty
	{
		private int _index;
		private List<FightClubRoomConnection> _connections;
		private List<Player> _members;
		
		public FightClubRoomParty(FightClubRoomTeam team)
		{
			_index = team.PARTY_INDEX++;
			_connections = new CopyOnWriteArrayList<>();
			_members = new CopyOnWriteArrayList<>();
		}
		public void addConnection(FightClubRoomConnection con)
		{
			_connections.add(con);
			for(Player member : con.getMembers())
			{
				_members.add(member);
			}
		}
		
		public void removeConnection(FightClubRoomConnection con)
		{
			_connections.remove(con);
			for(Player member : con.getMembers())
			{
				_members.remove(member);
			}
		}
		
		public void removeMember(Player player)
		{
			for(FightClubRoomConnection conn : getConnections())
				if(conn.getMembers().contains(player))
				{
					if(conn.getMembersCount() == 1)
						getConnections().remove(conn);
					else
						conn.getMembers().remove(player);
					break;
				}
			_members.remove(player);
		}
		
		int getMembersCount()
		{
			return _members.size();
		}
		
		public List<FightClubRoomConnection> getConnections()
		{
			return _connections;
		}
		
		public List<Player> getMembers()
		{
			return _members;
		}
		
		public int getIndex()
		{
			return _index;
		}
	}
	
	public class FightClubRoomConnection
	{
		List<Player> _members;
		
		public void setMembers(List<Player> members)
		{
			_members = members;
		}

		public List<Player> getMembers()
		{
			return _members;
		}
		
		public int getMembersCount()
		{
			return _members.size();
		}
	}
	
	/*
	 * 
	 * 
	 * Choosing team and party algorithm
	 * 
	 * 
	 * 
	 */
	
	/**
	 * Adding players to team and party
	 */
	private void addPlayers(FightClubRoomConnection conn)
	{
		chooseTeamAndParty(conn);
	}
	
	private FightClubRoomConnection createNewConnection(List<Player> players)
	{
		FightClubRoomConnection connection = new FightClubRoomConnection();
		connection.setMembers(players);
		
		return connection;
	}
	
	public static CLASSES getPlayerClassGroup(Player player)
	{
		CLASSES classType = null;
		for(CLASSES iClassType : CLASSES.values())
			for(ClassId id : iClassType.getClasses())
				if(id == player.getClassId())
					classType = iClassType;
		return classType;
	}
	
	private void chooseTeamAndParty(FightClubRoomConnection con)
	{
		//Starting to choose team
		int[][] minTeamPlayers = new int[_teams.size()][2];
		int[][] classesRatio = new int[_teams.size()][2];
		
		int index = 0;
		for(FightClubRoomTeam team : _teams)
		{
			int teamPlayers = team.getMembersCount();
			int classPlayers = 0;
			for(Player conMember : con.getMembers())
			{
				boolean found = false;
				for(FightClubRoomParty party : team.getPartys())
				{
					for(Player partyMember : party.getMembers())
					{
						if(getPlayerClassGroup(partyMember) == getPlayerClassGroup(conMember))
						{
							classPlayers--;
							found = true;
						}
					}
				}
				if(!found)
					if(getPlayerClassGroup(conMember) == CLASSES.HEALERS)
						classPlayers += 2;
					else
						classPlayers += 1;
			}
			
			minTeamPlayers[index][0] = index;
			minTeamPlayers[index][1] = teamPlayers;
			classesRatio[index][0] = index;
			classesRatio[index][1] = classPlayers;
			
			index++;
		}
		
		int[] winner = {-1, Integer.MIN_VALUE};
		for(int[] ratio : classesRatio)
			if(ratio[1] > winner[1])//Bigger - better
			{
				winner = ratio;
			}
			else if(ratio[1] == winner[1])
			{
				int winnerPlayers = 0;
				int nextPlayers = 0;
				for(int[] teams : minTeamPlayers)
					if(teams[0] == winner[0])
						winnerPlayers = teams[1];
					else if(teams[0] == ratio[0])
						nextPlayers = teams[1];
				if(nextPlayers < winnerPlayers)
					winner = ratio;
			}
		
		System.out.println("winner:"+winner[0]);
		
		//If connection is bigger than party count
		if(con.getMembersCount() > Party.MAX_SIZE)
		{
			for(FightClubRoomConnection newCon : splitConnection(con))
				addConnectionToParty(_teams.get(winner[0]), newCon);
		}
		else
		{
			addConnectionToParty(_teams.get(winner[0]), con);
		}
	}
	
	/**
	 * Adding Connection to party
	 */
	private void addConnectionToParty(FightClubRoomTeam team, FightClubRoomConnection players)
	{
		if(team.getPartys().isEmpty())
			team.getPartys().add(new FightClubRoomParty(team));//First Party
		
		//If just one party is enough
		if(team.getPartys().size() == 1 && team.getPartys().get(0).getMembersCount() + players.getMembersCount() <= Party.MAX_SIZE)
		{
			//Adding to first party
			team.getPartys().get(0).addConnection(players);
			return;
		}
		
		//Checking if we can add connection to any existing party
		boolean allPartysFull = true;
		for(FightClubRoomParty party : team.getPartys())
			if(party.getMembersCount() + players.getMembersCount() <= Party.MAX_SIZE)
				allPartysFull = false;
		
		//If we cant, create new party, add connection and some members from other partys to it
		if(allPartysFull)
		{
			FightClubRoomParty newPt = new FightClubRoomParty(team);
			newPt.addConnection(players);
			
			//Now look for members to add
			for(FightClubRoomParty existingPt : team.getPartys())
			{
				//Looking for All connections with ratio > 0(those classes already exists in party)
				for(FightClubRoomConnection existingConnection : existingPt.getConnections())
				{
					if(existingConnection.getMembersCount() + newPt.getMembersCount() > existingPt.getMembersCount())
						continue;
					
					int classPlayers = 0;
					for(Player conMember : existingConnection.getMembers())
					{
						boolean found = false;
						for(FightClubRoomParty party : team.getPartys())
						{
							for(Player partyMember : party.getMembers())
							{
								if(getPlayerClassGroup(partyMember) == getPlayerClassGroup(conMember) && !conMember.equals(partyMember))
								{
									classPlayers++;
									found = true;
								}
							}
						}
						
						if(!found)
						{
							if(getPlayerClassGroup(conMember) == CLASSES.HEALERS)
								classPlayers -= 2;
							else
								classPlayers -= 1;
						}
					}
					if(classPlayers > 0)
					{
						existingPt.removeConnection(existingConnection);
						newPt.addConnection(existingConnection);
						break;
					}
				}
			}
			//If party is still not full
			if(newPt.getMembersCount() < Party.MAX_SIZE)
			{
				boolean shouldStop = false;
				while(!shouldStop)
				{
					boolean addedAnything = false;
					//Checking just single players now
					//Check if party has lower number of members than new party, if not get something that isnt healer, tank and doesnt exist in new party
					loop:for(FightClubRoomParty existingPt : team.getPartys())
					{
						for(int i = existingPt.getConnections().size()-1;i>=0;i--)
						{
							if(existingPt.getMembersCount() > newPt.getMembersCount() + 1)
							{
								FightClubRoomConnection existingClass = existingPt.getConnections().get(i);
								if(existingClass.getMembersCount() == 1)
								{
									Player singlePlayer = existingClass.getMembers().get(0);
									if(getPlayerClassGroup(singlePlayer) != CLASSES.HEALERS && getPlayerClassGroup(singlePlayer) != CLASSES.TANKS && checkIfClassExists(newPt, singlePlayer))
									{
										existingPt.removeConnection(existingClass);
										newPt.addConnection(existingClass);
										addedAnything = true;
										break;
									}
								}
							}
							else
							{
								shouldStop = true;
								break loop;
							}
						}
					}
					//In case of infinite loop
					if(!addedAnything)
						shouldStop = true;
				}
			}
			//Adding newPt to partys
			team.getPartys().add(newPt);
		}
		else
		{
			//We need to find best place for new connection
			//We have checked that it exists.
			
			int[] partyMembers = new int[team.getPartys().size()];//Players in each Party
			int[] partyRatio = new int[team.getPartys().size()];//Same classes in each party
			
			//Bigger ratio - bigger chances to join party
			int index = 0;
			for(FightClubRoomParty party : team.getPartys())
			{
				int ratio = 0;
				for(Player conMember : players.getMembers())
				{
					boolean found = false;
					for(Player partyMember : party.getMembers())
					{
						if(getPlayerClassGroup(partyMember) == getPlayerClassGroup(conMember))
						{
							ratio--;
							found = true;
						}
					}
					if(!found)
					{
						if(getPlayerClassGroup(conMember) == CLASSES.HEALERS)
							ratio += 2;
						else
							ratio += 1;
					}
				}
				
				if(party.getMembersCount() + players.getMembersCount() >= Party.MAX_SIZE)
					ratio = Integer.MIN_VALUE;
				
				partyMembers[index] = party.getMembersCount();
				partyRatio[index] = ratio;
				index++;
			}
			
			int[] winner = {-1, Integer.MIN_VALUE};
			index = 0;
			for(int ratio : partyRatio)
			{
				//Jesli liczba tych samych klas jest mniejsza
				if(ratio > winner[1])
				{
					//Zapisz jako zwyciesca
					int[] newWinner = new int[2];
					newWinner[0] = index;
					newWinner[1] = ratio;
					winner = newWinner;
				}
				//Jesli jest taka sama, oblicz gdzie jest mniej ludzi
				else if(ratio == winner[1])
				{
					int winnerPlayers = 0;//Ilosc ludzi w winner
					int nextPlayers = 0;//Ilosc ludzi w aktualnej iteracji petli
					//Petla od 0 do ilosci party
					for(int partyIndex = 0; partyIndex < partyMembers.length ; partyIndex++)
					{
						System.out.println("index:"+partyIndex+" winner Index:"+winner[0]+" classesIndex:"+index);
						//Jesli partyIndex to index zwyciescy 
						if(partyIndex == winner[0])
							//Zapisz ilosc graczy
							winnerPlayers = partyMembers[partyIndex];
						//Jesli partyIndex to index aktualnej iteracji
						else if(partyIndex == index)
							//Zapisz ilosc graczy
							winnerPlayers = partyMembers[partyIndex];
					}
					
					System.out.println("winnerId:"+winner[0]+"winnerPlayers:"+winnerPlayers+" nextPlayers:"+nextPlayers);
					
					//Jesli w aktualnej iteracji jest mniej graczy niz w winnerze, zmien winnera
					if(nextPlayers < winnerPlayers)
					{
						int[] newWinner = new int[2];
						newWinner[0] = index;
						newWinner[1] = ratio;
						winner = newWinner;
					}
				}
				index++;
			}
			//Best choice was added, even if size is bigger than maxPlayersSize
			FightClubRoomParty choosenParty = team.getPartys().get(winner[0]);
			choosenParty.addConnection(players);
		}
	}
	
	private List<FightClubRoomConnection> splitConnection(FightClubRoomConnection con)
	{
		//This class is making more connections than one, if its bigger than max players in party
		int connectionsCount = (int)Math.ceil((double)con.getMembersCount()/Party.MAX_SIZE);
		System.out.println("connections count:"+connectionsCount);
		
		List<FightClubRoomConnection> connections = new CopyOnWriteArrayList<>();
		for(int i = 0;i<connectionsCount;i++)
		{
			FightClubRoomConnection newCon = new FightClubRoomConnection();
			newCon.setMembers(new ArrayList<Player>());
			connections.add(newCon);
		}
		
		for(Player player : con.getMembers())
		{
			int[][] minTeamPlayers = new int[connectionsCount][2];
			int[][] classesRatio = new int[connectionsCount][2];
			
			int index = 0;
			for(FightClubRoomConnection conn : connections)
			{
				int teamPlayers = conn.getMembersCount();
				int classPlayers = 0;
					
				boolean found = false;
				for(Player partyMember : conn.getMembers())
				{
					if(getPlayerClassGroup(partyMember) == getPlayerClassGroup(player))
					{
						classPlayers--;
						found = true;
					}
				}
				if(!found)
				{
					if(getPlayerClassGroup(player) == CLASSES.HEALERS)
						classPlayers += 2;
					else
						classPlayers += 1;
				}
				
				minTeamPlayers[index][0] = index;
				minTeamPlayers[index][1] = teamPlayers;
				classesRatio[index][0] = index;
				classesRatio[index][1] = classPlayers;
				
				index++;
			}
			
			int[] winner = {-1, Integer.MIN_VALUE};
			for(int[] ratio : classesRatio)
				if(ratio[1] > winner[1])//Bigger - better
				{
					winner = ratio;
				}
				else if(ratio[1] == winner[1])
				{
					int winnerPlayers = 0;
					int nextPlayers = 0;
					for(int[] teams : minTeamPlayers)
						if(teams[0] == winner[0])
							winnerPlayers = teams[1];
						else if(teams[0] == ratio[0])
							nextPlayers = teams[1];
					if(nextPlayers < winnerPlayers)
						winner = ratio;
				}
			
			connections.get(winner[0]).getMembers().add(player);
		}
		
		return connections;
	}
	
	private boolean checkIfClassExists(FightClubRoomParty newPt, Player singlePlayer)
	{
		for(Player member : newPt.getMembers())
			if(getPlayerClassGroup(member).equals(getPlayerClassGroup(singlePlayer)))
				return true;
		return false;
	}
}
